
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       slew_limiter.h
  * @author     baiyang
  * @date       2023-6-29
  ******************************************************************************
  */

#pragma once

#ifdef __cplusplus
extern "C"{
#endif

/*----------------------------------include-----------------------------------*/
#include <stdint.h>
#include "lpfilter.h"
/*-----------------------------------macro------------------------------------*/
#define SLEW_LIMITER_N_EVENTS 2 // number of positive and negative consecutive slew rate exceedance events recorded where a value of 2 corresponds to a complete cycle 
#define SLEW_LIMITER_WINDOW_MS 300 // time in msec required for a half cycle of the slowest oscillation frequency expected
#define SLEW_LIMITER_MODIFIER_GAIN 1.5f // ratio of modifier reduction to slew rate exceedance ratio
#define SLEW_LIMITER_DERIVATIVE_CUTOFF_FREQ 25.0f
/*----------------------------------typedef-----------------------------------*/
typedef struct slew_limiter* slew_limiter_t;
typedef const struct slew_limiter* slew_limiter_const_t;

struct slew_limiter {
    const float *slew_rate_max;
    const float *slew_rate_tau;
    LowPassFiltFloat slew_filter;
    float _output_slew_rate;
    float _modifier_slew_rate;
    float last_sample;
    float _max_pos_slew_rate;
    float _max_neg_slew_rate;
    uint32_t _max_pos_slew_event_ms;
    uint32_t _max_neg_slew_event_ms;
    uint8_t _pos_event_index;
    uint8_t _neg_event_index;
    uint32_t _pos_event_ms[SLEW_LIMITER_N_EVENTS];
    uint32_t _neg_event_ms[SLEW_LIMITER_N_EVENTS];
    bool _pos_event_stored;
    bool _neg_event_stored;
};

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
void slew_limiter_ctor(slew_limiter_t sl, const float *slew_rate_max, const float *slew_rate_tau);
float slew_limiter_modifier(slew_limiter_t sl, float sample, float dt);

/*
  get last oscillation slew rate
 */
static inline float slew_limiter_get_slew_rate(slew_limiter_const_t sl) {
    return sl->_output_slew_rate;
}

/*------------------------------------test------------------------------------*/

#ifdef __cplusplus
}
#endif



